package com.gallop.mq.core.template.handler.registry;

import com.gallop.mq.core.template.handler.DeliveryContext;
import com.gallop.mq.core.template.handler.DeliveryType;
import com.gallop.mq.core.template.handler.MessageDeliveryHandler;
import com.google.common.collect.Maps;

import java.util.Map;

public class DefaultHandlerRegistry implements MessageDeliveryHandlerRegistry {

    private final Map<DeliveryType, MessageDeliveryHandler> handlerMap = Maps.newConcurrentMap();
    private RegistryPreprocessor registryPreprocessor;

    @Override
    public <T> T createListener(DeliveryContext context) {
        return (T) this.registryPreprocessor.getListenerCreator().create(context);
    }

    @Override
    public void handleDelivery(DeliveryContext deliveryContext, Object... args) {
        ListenerArgs listenerArgs = ListenerArgs.of(args);
        DeliveryType deliveryType = (DeliveryType) this.registryPreprocessor.getDeliveryTypeProvider().apply(listenerArgs);
        if (deliveryType == null) {
            deliveryType = DeliveryType.SEND;
        }
        MessageDeliveryHandler handler = this.handlerMap.get(deliveryType);
        MessageDeliveryHandler.RpcInfo<?> rpcInfo = (MessageDeliveryHandler.RpcInfo<?>) this.registryPreprocessor.getRpcInfoProvider().apply(listenerArgs);
        Object raw = this.registryPreprocessor.getRawMessageProvider().apply(listenerArgs);
        Object incoming = this.registryPreprocessor.getMqMessageProvider().apply(raw);
        handler.handlerDelivery(deliveryContext, deliveryType, rpcInfo, incoming);
    }

    @Override
    public <T, M> void setPreprocessor(RegistryPreprocessor<T, M> registryPreprocessor) {
        this.registryPreprocessor = registryPreprocessor;
    }

    @Override
    public void registerHandler(DeliveryType deliveryType, MessageDeliveryHandler handler) {
        this.handlerMap.put(deliveryType, handler);
    }
}
